home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Icon 8.1 / msm-1 / icont.sit / lmem.c / lmem.c
Encoding:
C/C++ Source or Header  |  1992-11-10  |  13.5 KB  |  623 lines  |  [TEXT/MPS ]

  1. /*
  2.  * lmem.c -- memory initialization and allocation; also parses arguments.
  3.  */
  4.  
  5. #include "link.h"
  6. #include "tproto.h"
  7. #include "globals.h"
  8.  
  9. /*
  10.  * The following code is operating-system dependent [@lmem.01].  It includes
  11.  *  files that are system dependent.
  12.  */
  13.  
  14. #if PORT
  15.    /* nothing is needed */
  16. Deliberate Syntax Error
  17. #endif                    /* PORT */
  18.  
  19. #if AMIGA || ARM || ATARI_ST || MACINTOSH || VMS
  20.    /* nothing is needed */
  21. #endif                    /* AMIGA || ARM || ATARI_ST || ... */
  22.  
  23. #if OS2
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #endif                    /* OS@ */
  27.  
  28. #if MSDOS
  29. #if MWC
  30. #include <stat.h>
  31. #endif                    /* MWC */
  32. #if LATTICE
  33. #include <types.h>
  34. #include <stat.h>
  35. #endif                    /* LATTICE */
  36. #if MICROSOFT || INTEL_386 || ZTC_386 || HIGHC_386 || WATCOM
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #endif                    /* MICROSOFT || INTEL_386 || ...  */
  40. #if TURBO
  41. #include <sys/stat.h>
  42. #endif                    /* TURBO */
  43. #endif                    /* MSDOS */
  44.  
  45. #if MVS || VM
  46. #if SASC
  47. #include <fcntl.h>
  48. #endif                    /* SASC */
  49. #endif                    /* MVS || VM */
  50.  
  51. #if UNIX
  52. #ifndef ATT3B
  53. #ifdef CRAY
  54. #define word word_fubar
  55. #include <sys/types.h>
  56. #include <sys/stat.h>
  57. #undef word
  58. #else                    /* CRAY */
  59. #ifndef XWindows
  60. #include <sys/types.h>
  61. #endif                    /* XWindows */
  62. #include <sys/stat.h>
  63. #endif                    /* CRAY */
  64. #endif                    /* ATT3B */
  65. #endif                    /* UNIX */
  66.  
  67. /*
  68.  * End of operating-system specific code.
  69.  */
  70.  
  71. /*
  72.  * Prototypes.
  73.  */
  74.  
  75. hidden struct    lfile *alclfile    Params((char *name));
  76. hidden int    canread        Params((char *file));
  77. hidden int    trypath        Params((char *name,char *file));
  78.  
  79. #ifdef DeBugLinker
  80. hidden    novalue    dumpfiles    Params((noargs));
  81. #endif                    /* DeBugLinker */
  82.  
  83. #ifdef MultipleRuns
  84. hidden novalue    freelfile    Params((struct lfile *p));
  85. #endif                    /* MultipleRuns */
  86.  
  87. /*
  88.  * Memory initialization
  89.  */
  90.  
  91. struct gentry **lghash;        /* hash area for global table */
  92. struct ientry **lihash;        /* hash area for identifier table */
  93. struct fentry **lfhash;        /* hash area for field table */
  94.  
  95. struct lentry *lltable;        /* local table */
  96. struct centry *lctable;        /* constant table */
  97. struct ipc_fname *fnmtbl;    /* table associating ipc with file name */
  98. struct ipc_line *lntable;    /* table associating ipc with line number */
  99.  
  100. char *lsspace;            /* string space */
  101. word *labels;            /* label table */
  102. char *codeb;            /* generated code space */
  103.  
  104. struct ipc_fname *fnmfree;    /* free pointer for ipc/file name table */
  105. struct ipc_line *lnfree;    /* free pointer for ipc/line number table */
  106. word lsfree;            /* free index for string space */
  107. char *codep;            /* free pointer for code space */
  108.  
  109. struct fentry *lffirst;        /* first field table entry */
  110. struct fentry *lflast;        /* last field table entry */
  111. struct gentry *lgfirst;        /* first global table entry */
  112. struct gentry *lglast;        /* last global table entry */
  113.  
  114. static char *ipath;        /* path for iconx */
  115.  
  116. #ifdef MultipleRuns
  117. extern word pc;
  118. extern int fatals;
  119. extern int nlflag;
  120. extern int lstatics;
  121. extern int nfields;
  122. #endif                    /* MultipleRuns */
  123.  
  124. /*
  125.  * linit - scan the command line arguments and initialize data structures.
  126.  */
  127. novalue linit()
  128.    {
  129.    struct gentry **gp;
  130.    struct ientry **ip;
  131.    struct fentry **fp;
  132.  
  133.    llfiles = NULL;        /* Zero queue of files to link. */
  134.  
  135. #ifdef EnvVars
  136.    ipath = getenv(IPATH);
  137. #else                    /* EnvVars */
  138.    ipath = NULL;
  139. #endif                    /* EnvVars */
  140.  
  141.    if (ipath == NULL)
  142.  
  143. /*
  144.  * The following code is operating-system dependent [@lmem.02].  Set default
  145.  * for IPATH.
  146.  */
  147.  
  148. #if PORT
  149.    /* something is needed */
  150. Deliberate Syntax Error
  151. #endif                    /* PORT */
  152.  
  153. #if AMIGA
  154.    /*
  155.     * There is no environment, so set IPATH to the null string. The
  156.     *  current directory is searched anyway and there is no symbol
  157.     *  to force current path search.
  158.     */
  159.       ipath = "";
  160. #endif                    /* AMIGA */
  161.  
  162. #if ARM
  163.       ipath = "Icon: Lib:Icon.";
  164. #endif                    /* ARM */
  165.  
  166. #if ATARI_ST || UNIX
  167.       ipath = ".";
  168. #endif                    /* ATARI_ST || UNIX */
  169.  
  170. #if MSDOS || OS2
  171.       ipath = ";";
  172. #endif                    /* MSDOS || OS2 */
  173.  
  174. #if MACINTOSH
  175. #if MPW || LSC
  176.       ipath = ":";
  177. #endif                    /* MPW || LSC */
  178. #endif                    /* MACINTOSH */
  179.  
  180. #if MVS
  181. #if SASC
  182.       ipath = "iconlib ddn:::lib";
  183. #else                    /* SASC */
  184.       ipath = "";
  185. #endif                    /* SASC */
  186. #endif                    /* MVS */
  187.  
  188. #if VM
  189.       ipath = "";
  190. #endif                                  /* VM */
  191.  
  192. #if VMS
  193.       ipath = "[]";
  194. #endif                    /* VMS */
  195.  
  196. /*
  197.  * End of operating-system specific code.
  198.  */
  199.  
  200.    /*
  201.     * Allocate the various data structures that are used by the linker.
  202.     */
  203.    lghash   = (struct gentry **) tcalloc(ghsize, sizeof(struct gentry *));
  204.    lihash   = (struct ientry **) tcalloc(ihsize, sizeof(struct ientry *));
  205.    lfhash   = (struct fentry **) tcalloc(fhsize, sizeof(struct fentry *));
  206.  
  207.    lltable  = (struct lentry *) tcalloc(lsize, sizeof(struct lentry));
  208.    lctable  = (struct centry *) tcalloc(csize, sizeof(struct centry));
  209.  
  210.    lnfree = lntable  = (struct ipc_line*)tcalloc(nsize,sizeof(struct ipc_line));
  211.  
  212.    lsspace = (char *) tcalloc(stsize, sizeof(char));
  213.    lsfree = 0;
  214.  
  215.    fnmtbl = (struct ipc_fname *) tcalloc(fnmsize, sizeof(struct ipc_fname));
  216.    fnmfree = fnmtbl;
  217.  
  218.    labels  = (word *) tcalloc(maxlabels, sizeof(word));
  219.    codep = codeb = (char *) tcalloc(maxcode, 1);
  220.  
  221.    lffirst = NULL;
  222.    lflast = NULL;
  223.    lgfirst = NULL;
  224.    lglast = NULL;
  225.  
  226.    /*
  227.     * Zero out the hash tables.
  228.     */
  229.    for (gp = lghash; gp < &lghash[ghsize]; gp++)
  230.       *gp = NULL;
  231.    for (ip = lihash; ip < &lihash[ihsize]; ip++)
  232.       *ip = NULL;
  233.    for (fp = lfhash; fp < &lfhash[fhsize]; fp++)
  234.       *fp = NULL;
  235.  
  236. #ifdef MultipleRuns
  237.  
  238.    /*
  239.     * Initializations required for repeated program runs.
  240.     */
  241.  
  242.    pc = 0;                /* In lcode.c    */
  243.    nrecords = 0;            /* In lglob.c    */
  244.  
  245. #ifdef EventMon
  246.    colmno = 0;                /* In link.c    */
  247. #endif                    /* EventMon */
  248.  
  249.    lineno = 0;                /* In link.c    */
  250.    fatals = 0;                /* In link.c    */
  251.    nlflag = 0;                /* In llex.c    */
  252.    lstatics = 0;            /* In lsym.c    */
  253.    nfields = 0;                /* In lsym.c    */
  254. #endif                    /* MultipleRuns */
  255.  
  256.    /*
  257.     * Install "main" as a global variable in order to insure that it
  258.     *  is the first global variable.  iconx/start.s depends on main
  259.     *  being global number 0.
  260.     */
  261.    putglobal(instid("main"), F_Global, 0, 0);
  262.    }
  263.  
  264. #ifdef DeBugLinker
  265. /*
  266.  * dumplfiles - print the list of files to link.  Used for debugging only.
  267.  */
  268.  
  269. novalue dumplfiles()
  270.    {
  271.    struct lfile *p,*lfls;
  272.  
  273.    fprintf(stderr,"lfiles:\n");
  274.    lfls = llfiles;
  275.    while (p = getlfile(&lfls))
  276.        fprintf(stderr,"'%s'\n",p->lf_name);
  277.    fflush(stderr);
  278.    }
  279. #endif                    /* DeBugLinker */
  280.  
  281. /*
  282.  * alsolink - create an lfile structure for the named file and add it to the
  283.  *  end of the list of files (llfiles) to generate link instructions for.
  284.  */
  285. static char *pptr;
  286. novalue alsolink(name)
  287. char *name;
  288.    {
  289.    struct lfile *nlf, *p;
  290.    char file[256], ok;
  291.  
  292.    ok = 0;
  293.    if (canread(name)) {
  294.       ok++;
  295.       strcpy(file, name);
  296.       }
  297.    else {
  298.       /*
  299.        * Can't find name in current directory so try paths in
  300.        *   IPATH if there are any. (IPATH cannot override the
  301.        *   current-directory-first strategy so there is probably
  302.        *   no reason to initialize IPATH to the various current
  303.        *   directory markers as is done above, since this will
  304.        *   only result in a duplicate failed search. Note that
  305.        *   the access test which is done above in some systems
  306.        *   will have already caused ilink to exit if name is
  307.        *   not found in the current directory anyway so ipath
  308.        *   was never able to search other paths first in any case.)
  309.        */
  310.  
  311. #ifdef Xver
  312. xver(lmem.1)
  313. #endif                    /* Xver */
  314.  
  315. #ifndef Xver
  316.       pptr = ipath;
  317. #endif                    /* Xver */
  318.  
  319.       while (trypath(name, file)) {
  320.          if (canread(file)) {
  321.             ok++;
  322.             break;
  323.             }
  324.          }
  325.       }
  326.  
  327.    if (!ok)
  328.      quitf("cannot resolve reference to file '%s'",name);
  329.  
  330.    nlf = alclfile(file);
  331.    if (llfiles == NULL) {
  332.       llfiles = nlf;
  333.       }
  334.    else {
  335.       p = llfiles;
  336.       while (p->lf_link != NULL) {
  337.         if (strcmp(p->lf_name,file) == 0)
  338.            return;
  339.         p = p->lf_link;
  340.         }
  341.       if (strcmp(p->lf_name,file) == 0)
  342.         return;
  343.       p->lf_link = nlf;
  344.       }
  345.    }
  346.  
  347. /*
  348.  * getlfile - return a pointer (p) to the lfile structure pointed at by lptr
  349.  *  and move lptr to the lfile structure that p points at.  That is, getlfile
  350.  *  returns a pointer to the current (wrt. lptr) lfile and advances lptr.
  351.  */
  352. struct lfile *getlfile(lptr)
  353. struct lfile **lptr;
  354.    {
  355.    struct lfile *p;
  356.  
  357.    if (*lptr == NULL)
  358.       return (struct lfile *)NULL;
  359.    else {
  360.       p = *lptr;
  361.       *lptr = p->lf_link;
  362.       return p;
  363.       }
  364.    }
  365.  
  366. /*
  367.  * canread - see if file can be read and be sure that it's just an
  368.  *  ordinary file.
  369.  */
  370. static int canread(file)
  371. char *file;
  372.    {
  373.  
  374. /*
  375.  * The following code is operating-system dependent [@lmem.03]. Check to see if
  376.  *  .u1 file can be read.
  377.  */
  378.  
  379. #if PORT
  380.    /* something is needed */
  381. Deliberate Syntax Error
  382. #endif                    /* PORT */
  383.  
  384. #if AMIGA || ATARI_ST || VMS
  385.    if (access(file,4) == 0)
  386.       return 1;
  387. #endif                    /* AMIGA || ATARI_ST || VMS */
  388.  
  389. #if ARM
  390.    {
  391.    FILE *f;
  392.    if ((f = fopen(file,ReadText)) != NULL) {
  393.       fclose(f);
  394.       return 1;
  395.       }
  396.    }
  397. #endif                    /* ARM */
  398.  
  399. #if MACINTOSH
  400. #if MPW || LSC
  401.    {
  402.    FILE *f;
  403.    if ((f = fopen(file,ReadText)) != NULL) {
  404.       fclose(f);
  405.       return 1;
  406.       }
  407.    }
  408. #endif                    /* MPW || LSC */
  409. #endif                    /* MACINTOSH */
  410.  
  411. #if MSDOS || OS2 || UNIX
  412. #if INTEL_386
  413.    char lclname[MaxFileName];
  414.    if (access( makename(lclname,(char *)NULL,file,U1Suffix), 4 ) == 0 )
  415.       return 1;
  416. #else                    /* INTEL_386 */
  417.    struct stat statb;
  418.    if (access(file,4) == 0) {
  419.       stat(file,&statb);
  420.       if (statb.st_mode & S_IFREG)
  421.          return 1;
  422.       }
  423. #endif                    /* INTEL_386 */
  424. #endif                    /* MSDOS || ... */
  425.  
  426. #if MVS || VM
  427.    char lclname[MaxFileName];
  428. #if SASC
  429.    if (access(makename(lclname,(char*)NULL,file,U1Suffix),R_OK) == 0)
  430.       return 1;
  431. #else                    /* SASC */
  432.    FILE *f;                     /* can't use access because it will */
  433.                                 /* accept LRECL, etc. */
  434.  
  435.    if ((f = fopen(makename(lclname,(char *)NULL,file,U1suffix),
  436.       ReadText)) != NULL) {
  437.       fclose(f);
  438.       return 1;
  439.       }
  440. #endif                    /* SASC */
  441. #endif                    /* MVS || VM */
  442.  
  443. /*
  444.  * End of operating-system specific code.
  445.  */
  446.  
  447.    return 0;
  448.    }
  449.  
  450. #ifdef Xver
  451. xver(lmem.2)
  452. #endif                    /* Xver */
  453.  
  454. #ifndef Xver
  455. /*
  456.  * trypath - form a file name in file by concatenating name onto the
  457.  *  next path element.
  458.  */
  459. static int trypath(name,file)
  460. char *name, *file;
  461.    {
  462.    char c;
  463.  
  464. #if MACINTOSH && MPW
  465. #define PATH_SEP ','
  466. #else                /* MACINTOSH && MPW */
  467. #define PATH_SEP ' '
  468. #endif                /* MACINTOSH && MPW */
  469.  
  470.    while (*pptr == PATH_SEP)
  471.       pptr++;
  472.    if (!*pptr)
  473.       return 0;
  474.    do {
  475.       c = (*file++ = *pptr++);
  476.       }
  477.       while (c != PATH_SEP && c);
  478.    pptr--;
  479.    file--;
  480.  
  481. /*
  482.  * The following code is operating-system dependent [@lmem.04].  Append path
  483.  *  character.
  484.  */
  485.  
  486. #if PORT
  487.    /* nothing is needed */
  488. Deliberate Syntax Error
  489. #endif                    /* PORT */
  490.  
  491. #if AMIGA
  492.    file--;
  493.    switch (*file) {
  494.  
  495.       case ':':
  496.       case '/':
  497.                  file++;
  498.                  break;       /* add nothing, delimiter already there */
  499.       default:
  500.                  *file++ = '/';
  501.       }
  502. #endif                    /* AMIGA */
  503.  
  504. #if ARM || ATARI_ST || MACINTOSH || VM || VMS
  505.    /* nothing is needed */
  506. #endif                    /* ARM || ATARI_ST || MACINTOSH ... */
  507.  
  508. #if MVS
  509.    *file++ = '(';
  510. #endif                    /* MVS */
  511.  
  512. #if UNIX || MSDOS || OS2
  513. #if HIGHC_386
  514.    *file++ = '\\';
  515. #else                    /* HIGHC_386 */
  516.    *file++ = '/';            /* should check for delimiter */
  517. #endif                    /* HIGHC_386 */
  518. #endif                    /* UNIX || MSDOS || OS2 */
  519.  
  520. /*
  521.  * End of operating-system specific code.
  522.  */
  523.  
  524.    while (*file++ = *name++);
  525.  
  526. #if MVS
  527.    file[-1] = ')';
  528. #endif                    /* MVS */
  529.    *file = 0;
  530.    return 1;
  531.    }
  532. #endif                    /* Xver */
  533.  
  534. /*
  535.  * alclfile - allocate an lfile structure for the named file, fill
  536.  *  in the name and return a pointer to it.
  537.  */
  538. static struct lfile *alclfile(name)
  539. char *name;
  540.    {
  541.    struct lfile *p;
  542.  
  543.    p = (struct lfile *) alloc(sizeof(struct lfile));
  544.    p->lf_link = NULL;
  545.    p->lf_name = salloc(name);
  546.    return p;
  547.    }
  548.  
  549. #ifdef MultipleRuns
  550. /*
  551.  * freelfile - free memory of an lfile structure.
  552.  */
  553. static novalue freelfile(p)
  554. struct lfile *p;
  555.    {
  556.    free((char *)p->lf_name);
  557.    free((char *) p);
  558.    }
  559. #endif                        /* MultipleRuns */
  560.  
  561. /*
  562.  * lmfree - free memory used by the linker
  563.  */
  564. novalue lmfree()
  565.    {
  566.    struct fentry *fp, *fp1;
  567.    struct gentry *gp, *gp1;
  568.    struct rentry *rp, *rp1;
  569.    struct ientry *ip, *ip1;
  570.    struct lfile *lf, *nlf;
  571.    int i;
  572.  
  573.    for (i = 0; i < ihsize; ++i)
  574.       for (ip = lihash[i]; ip != NULL; ip = ip1) {
  575.            ip1 = ip->i_blink;
  576.            free((char *)ip);
  577.            }
  578.  
  579.    free((char *) lghash);   lghash = NULL;
  580.    free((char *) lihash);   lihash = NULL;
  581.    free((char *) lfhash);   lfhash = NULL;
  582.    free((char *) lltable);   lltable = NULL;
  583.    free((char *) lctable);   lctable = NULL;
  584.    free((char *) lntable);   lntable = NULL;
  585.    free((char *) lsspace);   lsspace = NULL;
  586.    free((char *) fnmtbl);   fnmtbl = NULL;
  587.    free((char *) labels);   labels = NULL;
  588.    free((char *) codep);   codep = NULL;
  589.  
  590.    for (fp = lffirst; fp != NULL; fp = fp1) {
  591.       for(rp = fp->f_rlist; rp != NULL; rp = rp1) {
  592.          rp1 = rp->r_link;
  593.          free((char *)rp);
  594.          }
  595.       fp1 = fp->f_nextentry;
  596.       free((char *)fp);
  597.       }
  598.    lffirst = NULL;
  599.    lflast = NULL;
  600.  
  601.    for (gp = lgfirst; gp != NULL; gp = gp1) {
  602.       gp1 = gp->g_next;
  603.       free((char *)gp);
  604.       }
  605.    lgfirst = NULL;
  606.    lglast = NULL;
  607.  
  608. #ifdef MultipleRuns
  609.    for (lf = llfiles; lf != NULL; lf = nlf) {
  610.       nlf = lf->lf_link;
  611.       freelfile(lf);
  612.       }
  613.    llfiles = NULL;
  614.  
  615. #if MACINTOSH
  616. #if MPW
  617. /* #pragma unused(nlf,lf) */
  618. #endif                    /* MPW */
  619. #endif                    /* MACINTOSH */
  620. #endif                    /* MultipleRuns */
  621.  
  622.    }
  623.